package relmap

import (
	"micro-rulego/internal/util"
	"sync"
)

// A->B(One-to-One)
// A<-B(One-to-One)
var _ util.Relations = &OneToOne{}

type OneToOne struct {
	entityAToB map[uint32]uint32
	entityBToA map[uint32]uint32
	lock       sync.RWMutex
}

func NewOneToOne() *OneToOne {
	return &OneToOne{
		entityAToB: make(map[uint32]uint32),
		entityBToA: make(map[uint32]uint32),
	}
}

func (m *OneToOne) AddRelation(entityA, entityB uint32) bool {
	m.lock.Lock()
	defer m.lock.Unlock()

	// 检查 entityA 是否已经与其他 entityB 关联
	if existingB, exists := m.entityAToB[entityA]; exists {
		if existingB != entityB { // 如果 entityA 已经与其他 entityB 关联，则返回 false
			return false
		}
	}

	// 检查 entityB 是否已经与其他 entityA 关联
	if existingA, exists := m.entityBToA[entityB]; exists {
		if existingA != entityA { // 如果 entityB 已经与其他 entityA 关联，则返回 false
			return false
		}
	}

	// 添加 entityA 到 entityB 的关系
	m.entityAToB[entityA] = entityB
	// 添加 entityB 到 entityA 的关系
	m.entityBToA[entityB] = entityA

	return true
}

func (m *OneToOne) RemoveRelation(entityA, entityB uint32) {
	m.lock.Lock()
	defer m.lock.Unlock()

	// 移除 entityA 到 entityB 的关系
	if existingB, exists := m.entityAToB[entityA]; exists && existingB == entityB {
		delete(m.entityAToB, entityA)
	}

	// 移除 entityB 到 entityA 的关系
	if existingA, exists := m.entityBToA[entityB]; exists && existingA == entityA {
		delete(m.entityBToA, entityB)
	}
}

func (m *OneToOne) GetRelatedToA(entityA uint32) []uint32 {
	m.lock.RLock()
	defer m.lock.RUnlock()

	entityB, exists := m.entityAToB[entityA]
	if exists {
		return []uint32{entityB}
	}
	return []uint32{}
}

func (m *OneToOne) GetRelatedToB(entityB uint32) []uint32 {
	m.lock.RLock()
	defer m.lock.RUnlock()

	entityA, exists := m.entityBToA[entityB]
	if exists {
		return []uint32{entityA}
	}
	return []uint32{}
}
